'''
邮箱激活token操作类
需要在common的上一级目录下执行，这样worker进程才能识别到django的根目录下的所有路径,
在common内执行，会报错ModuleNotFoundError: No module named 'common'
D:\project\blog> celery -A common.celery_task worker -l info -P eventlet

'''

from django.core.mail import send_mail
from django.urls import reverse
from django.template import loader
from django.conf import settings
from itsdangerous import URLSafeTimedSerializer as UTSerializer
from common.celery_task.celery import app
from common.logger import log
import os




class Token(object):
    '''
    利用URLSafeTimedSerializer模块签发token，并且设置失效时间,
    URLSafeTimedSerializer:给不信任的环境发送信息的时候，加密信息，服务端配置secret_key，配合加密算法，用来
    加密，相当于私钥，生产环境可以使用环境变量传入
    '''

    def __init__(self):
        '''
        传入私钥，注意保护好该私钥
        生产环境建议使用环境变量传入os.environ.get('secret_key')
        '''
        self.serializer = UTSerializer(secret_key= os.environ.get('EMAIL_SECRET_KEY'))

    # 生成token，加密，加密对象是username
    def generate_validate_token(self, username):
        return self.serializer.dumps(username)

    # 验证token，解密
    def confirm_validate_token(self, token, expiration= 60*60):
        '''
        :param expiration: 有效期，单位s；
            dumps生产token时会记录创建时间，loads传入有效期，会与dumps的创建时间
            比较，当前时刻（距离创建时间）是否超过了60s
        :return: 返回username
        '''
        return self.serializer.loads(token, max_age= expiration)

    # 删除token，需要重新拿到username
    def remove_validate_token(self, token):
        return self.serializer.loads(token)

# 创建toekn对象
get_token_obj = Token()


# 发送激活邮件
@app.task
def send_email(username, host, email):

    token = get_token_obj.generate_validate_token(username)
    # 拿到token，构造激活路由；reverse反向解析('activate/(?P<token>.*)')
    eml_url = "http://" + host + reverse("active",
                                         kwargs={'token': token})

    # 加载模板
    html = loader.get_template('user/email_active/active.html'
                               ).render({'eml_url': eml_url})

    try:
        # 发送邮件
        send_mail(settings.SUBJECT,   # 主题
                  '',                 #  邮件信息，使用html_message，则不需要传入
                  settings.DEFAULT_FROM_EMAIL,  #  发件人
                  [email],             #  收件人，传入list
                  html_message= html)  # 邮件网页内容
        log.info('激活邮件发送成功')
    except Exception as e:
        log.error('激活邮件发送失败', e)